package com.portal.hiloventana;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Properties;

import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JWindow;

import org.apache.log4j.Logger;

import com.portal.notification.Message;

/**
 * Server side.
 *
 */
public class App extends Thread {
	/**
	 * Properties for sending mail.
	 */
	private Properties sessionProperties;
	/**
	 * Ventana de notificacion.
	 */
	private JWindow notificacion;
	/**
	 * Etiqueta para mostrar el mensaje.
	 */
	private JLabel mensaje;
	/**
	 * Contenedor para el mensaje.
	 */
	private JScrollPane scroll;
	/**
	 * Componente para mostrar el log del cambio.
	 */
	private JTextArea log;
	/**
	 * Botón para mostrar el componente del log.
	 */
	private JButton showLog;
	/**
	 * Botón para cerrar el componenten del log.
	 */
	private JButton cerrar;
	/**
	 * Logger de la aplicación.
	 */
	private final Logger logger = Logger.getLogger(App.class);
	/**
	 * Constructor por defecto.
	 */
	public App() {
		logger.info("Inicio del servidor");
		if (loadPropertie()) {
			create();
			start();
		} else {
			logger.error("Propiedades no encontradas o cargadas");
		}
	}
	/**
	 * Crea el servidor.
	 */
	private void create() {
		notificacion = new JWindow();
		notificacion.setLayout(new FlowLayout());
		mensaje = new JLabel("el usuario");
		mensaje.setAutoscrolls(true);
		log = new JTextArea(5, 50);
		log.setEditable(false);
		scroll = new JScrollPane(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
	            JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
		scroll.setViewportView(log);
		showLog = new JButton("Show log");
		cerrar = new JButton("X");
		cerrar.addActionListener(new ActionListener() {
			public void actionPerformed(final ActionEvent e) {
				wakeUp();
			}
		});
		showLog.addActionListener(new ActionListener() {
			public void actionPerformed(final ActionEvent e) {
				if (log.isVisible()) {
					scroll.setVisible(false);
					log.setVisible(false);
					notificacion.pack();
				} else {
					scroll.setVisible(true);
					log.setVisible(true);
					notificacion.pack();
				}
			}
		});
		notificacion.addMouseListener(new MouseListener() {
			public void mouseReleased(MouseEvent e) {
				// TODO Auto-generated method stub
			}
			public void mousePressed(MouseEvent e) {
				// TODO Auto-generated method stub
			}
			public void mouseExited(MouseEvent e) {
				// TODO Auto-generated method stub
			}
			public void mouseEntered(MouseEvent e) {
				// TODO Auto-generated method stub
			}
			public void mouseClicked(MouseEvent e) {
				notificacion.setVisible(false);
			}
		});
		log.setVisible(false);
		scroll.setVisible(false);
		mensaje.setBackground(Color.RED);
		notificacion.setBackground(Color.RED);
		notificacion.setMaximumSize(new Dimension(800, 200));
		notificacion.add(mensaje);
		notificacion.add(scroll);
		notificacion.add(showLog);
		notificacion.add(cerrar);
	}
	/**
	 * Despierta el servidor.
	 */
	private void wakeUp() {
		interrupt();
		notificacion.setVisible(false);
	}
	@Override
	public void run() {
		try {
			ServerSocket serverSocket = null;
			Socket socket = null;
			serverSocket = new ServerSocket(Integer.valueOf(sessionProperties.get("servidor.port").toString()));
			while (true) {
				scroll.setVisible(false);
				log.setVisible(false);
				notificacion.pack();
				socket = serverSocket.accept();
				ObjectInputStream in  = new ObjectInputStream(socket.getInputStream());
				Message messageObject = (Message) in.readObject();
				mensaje.setText(messageObject.getUsuario() + ":" + messageObject.getCambios());
				logger.info("Cambio recibido: " + messageObject.getUsuario() + "-" + messageObject.getCambios());
				log.setText("");
				log.append(messageObject.getLog());
				notificacion.pack();
				notificacion.setAlwaysOnTop(true);
				notificacion.setVisible(true);
				logger.info("Esperando Cambio");
				try {
					sleep(Long.valueOf(sessionProperties.get("servidor.delay").toString()));
				} catch (InterruptedException e) {
					logger.info("Despertar forzado");
				}
				logger.info("Despertando");
				notificacion.setVisible(false);
			}
		} catch (IOException e) {
			logger.error("IOException: " + e.getLocalizedMessage());
		} catch (ClassNotFoundException e) {
			logger.error("ClassNotFoundException: " + e.getLocalizedMessage());
		}
	}
	/**
	 * Load a existing propertie file into the same path of directory.
	 * @return True - if the properties has been loaded.
	 * False - if the properties has not been loaded.
	 */
	private Boolean loadPropertie() {
		try {
			FileInputStream inSession = new FileInputStream("session.properties");
			sessionProperties = new Properties();
			sessionProperties.load(inSession);
			inSession.close();
		} catch (IOException e) {
			e.printStackTrace();
			return Boolean.FALSE;
		}
		return Boolean.TRUE;
	}
	/**
	 * Main.
	 * @param args Argumentos.
	 */
    public static void main(final String[] args) {
        new App();
    }
}
